#include "ZeroGene.h"

#include <cstdlib>

ZeroGene::ZeroGene()
{
	mGeneF = NULL;
	mGeneM = NULL;
	mGeneFSize = 0;
	mGeneMSize = 0;
}

ZeroGene::~ZeroGene()
{
	if (mGeneF)
		delete [] mGeneF;
	if (mGeneM)
		delete [] mGeneM;
}

char* ZeroGene::getGeneF()
{
	return mGeneF;
}

char* ZeroGene::getGeneM()
{
	return mGeneM;
}

int ZeroGene::getGeneFSize()
{
	return mGeneFSize;
}

int ZeroGene::getGeneMSize()
{
	return mGeneMSize;
}

void ZeroGene::setGeneF(char *geneF, int geneFSize)
{
	if (mGeneF)
		delete [] mGeneF;
	mGeneFSize = geneFSize;
	mGeneF = new char[mGeneFSize];
	for (int i = 0;i < mGeneFSize;i++)
		mGeneF[i] = geneF[i];
}

void ZeroGene::setGeneM(char *geneM, int geneMSize)
{
	if (mGeneM)
		delete [] mGeneM;
	mGeneMSize = geneMSize;
	mGeneM = new char[mGeneMSize];
	for (int i = 0;i < mGeneMSize;i++)
		mGeneM[i] = geneM[i];
}

ZeroGene* ZeroGene::crossover(ZeroGene *gene)
{
	ZeroGene *newGene = new ZeroGene();
	ZeroGene *geneA = this->copy();
	ZeroGene *geneB = gene->copy();
	if (rand() % 2 == 0)
		newGene->setGeneF(geneA->getGeneF(), geneA->getGeneFSize());
	else
		newGene->setGeneF(geneA->getGeneM(), geneA->getGeneMSize());
	if (rand() % 2 == 0)
		newGene->setGeneM(geneB->getGeneF(), geneB->getGeneFSize());
	else
		newGene->setGeneM(geneB->getGeneM(), geneB->getGeneMSize());
	return newGene;
}

ZeroGene* ZeroGene::copy()
{
	ZeroGene *newGene = new ZeroGene();
	char *geneF, *geneM, *tmpF, *tmpM;
	int geneFSize, geneMSize, tmpSize;
	int posFA, posFB, posMA, posMB, curA, curB;
	tmpSize = mGeneFSize + mGeneMSize;
	geneF = new char[tmpSize];
	geneM = new char[tmpSize];
	tmpF = new char[tmpSize];
	tmpM = new char[tmpSize];
	for (int i = 0;i < mGeneFSize;i++)
		geneF[i] = mGeneF[i];
	geneFSize = mGeneFSize;
	for (int i = 0;i < mGeneMSize;i++)
		geneM[i] = mGeneM[i];
	geneMSize = mGeneMSize;
	while (rand() % 20 == 0) {
		for (int i = 0;i < geneFSize;i++)
			tmpF[i] = geneF[i];
		for (int i = 0;i < geneMSize;i++)
			tmpM[i] = geneM[i];
		posFA = rand() % geneFSize;
		posFB = posFA + rand() % (geneFSize - posFA);
		posMA = rand() % geneMSize;
		posMB = posMA + rand() % (geneMSize - posMA);
		curA = posFA;
		curB = posMA;
		for (;curB <= posMB;)
			geneF[curA++] = tmpM[curB++];
		curB = posFB + 1;
		for (;curB <= geneFSize;)
			geneF[curA++] = tmpF[curB++];
		curA = posMA;
		curB = posFA;
		for (;curB < posFB;)
			geneM[curA++] = tmpF[curB++];
		curB = posMB + 1;
		for (;curB < geneMSize;)
			geneM[curA++] = tmpM[curB++];
		geneFSize += (posMB - posMA) - (posFB - posFA);
		geneMSize += (posFB - posFA) - (posMB - posMA);
	}
	newGene->setGeneF(geneF, geneFSize);
	newGene->setGeneM(geneM, geneMSize);
	delete [] geneF;
	delete [] geneM;
	delete [] tmpF;
	delete [] tmpM;
	return newGene;
}

ZeroGene* ZeroGene::RandomGene()
{
	ZeroGene *newGene = new ZeroGene();
	char *gene;
	int geneSize = rand() % 30 + 3;
	gene = new char[geneSize];
	for (int i = 0;i < geneSize;i++)
		gene[i] = rand() & 0xff;
	newGene->setGeneF(gene, geneSize);
	newGene->setGeneM(gene, geneSize);
	return newGene;
}
